{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## _*Variational Quantum Classifier*_\n",
    "\n",
    "The QSVM notebook demonstrates a kernel based approach. This notebook shows a variational method.\n",
    "\n",
    "For further information please see: [https://arxiv.org/pdf/1804.11326.pdf](https://arxiv.org/pdf/1804.11326.pdf)\n",
    "\n",
    "\n",
    "**This notebook shows the variational quantum classifier method.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit.ml.datasets import ad_hoc_data\n",
    "from qiskit import BasicAer\n",
    "from qiskit.aqua import QuantumInstance\n",
    "from qiskit.aqua.algorithms import VQC\n",
    "from qiskit.aqua.components.optimizers import SPSA\n",
    "from qiskit.circuit.library import TwoLocal, ZZFeatureMap\n",
    "from qiskit.aqua.utils import split_dataset_to_data_and_labels, map_label_to_class_name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First we prepare the dataset, which is used for training, testing and the finally prediction.\n",
    "\n",
    "*Note: You can easily switch to a different dataset, such as the Breast Cancer dataset, by replacing 'ad_hoc_data' to 'Breast_cancer' below.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'A': 0, 'B': 1}\n"
     ]
    }
   ],
   "source": [
    "feature_dim = 2 # dimension of each data point\n",
    "training_dataset_size = 20\n",
    "testing_dataset_size = 10\n",
    "random_seed = 10598\n",
    "shots = 1024\n",
    "\n",
    "sample_Total, training_input, test_input, class_labels = ad_hoc_data(\n",
    "    training_size=training_dataset_size, \n",
    "    test_size=testing_dataset_size, \n",
    "    n=feature_dim, gap=0.3, plot_data=True\n",
    ")\n",
    "datapoints, class_to_label = split_dataset_to_data_and_labels(test_input)\n",
    "print(class_to_label)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We construct the vqc instance directly from the classes. The programmatic approach offers the users better accessibility, e.g., the users can access the internal state of vqc instance or invoke the methods of the instance. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we create the vqc in the programmatic approach.\n",
    "- we build the optimizer instance (required by the vqc instance) by instantiating the class SPSA.\n",
    "- We build the feature map instance (required by the vqc instance) by instantiating the class ZZFeatureMap.\n",
    "- We build the varitional form instance (required by the vqc instance) by instantiating the class TwoLocal.\n",
    "- We build the vqc instance by instantiating the class VQC. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "optimizer = SPSA(max_trials=100, c0=4.0, skip_calibration=True)\n",
    "optimizer.set_options(save_steps=1)\n",
    "feature_map = ZZFeatureMap(feature_dimension=feature_dim, reps=2)\n",
    "var_form = TwoLocal(feature_dim, ['ry', 'rz'], 'cz', reps=3)\n",
    "vqc = VQC(optimizer, feature_map, var_form, training_input, test_input)\n",
    "quantum_instance = QuantumInstance(backend, shots=shots, seed_simulator=random_seed, seed_transpiler=random_seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we run it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "testing success ratio:  1.0\n"
     ]
    }
   ],
   "source": [
    "result = vqc.run(quantum_instance)\n",
    "print(\"testing success ratio: \", result['testing_accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The programmatic approach allows the users to invoke APIs upon the vqc instance directly. In the following, we invoke the API \"predict\" upon the trained vqc instance to predict the labels for the newly provided data input.\n",
    "\n",
    "Use the trained model to evaluate data directly, and we store a label_to_class and class_to_label for helping converting between label and class name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prediction:   [0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1]\n"
     ]
    }
   ],
   "source": [
    "predicted_probs, predicted_labels = vqc.predict(datapoints[0])\n",
    "predicted_classes = map_label_to_class_name(predicted_labels, vqc.label_to_class)\n",
    "print(\"prediction:   {}\".format(predicted_labels))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
